package com.example.demo.tenant;

import com.example.demo.common.DbConstants;
import com.example.demo.dto.TenantDbConfigDTO;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.engine.jdbc.connections.spi.AbstractDataSourceBasedMultiTenantConnectionProviderImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

/**
 * 这个类是Hibernate框架拦截sql语句并在执行sql语句之前更换数据源提供的类
 * @version 1.0
 */
@Slf4j
@Component
public class MultiTenantConnectionProvider extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl {

    @Autowired
    private DataSourceProperties dataSourceProperties;
    @Autowired


    /**
     * 在没有提供tenantId的情况下返回默认数据源
     */
    @Override
    protected DataSource selectAnyDataSource() {
        return selectDataSource(DbConstants.DEFAULT_DATABASE);
    }

    /**
     * 提供了tenantId的话就根据ID来返回数据源
     */
    @Override
    public DataSource selectDataSource(String tenantId) {

        // 当前租户数据源已经存在 不创建Datasource
        log.info("{}", "====================================================");
        log.info("Is Get DataSource: {}", TenantContextHolder.dataSourceMap.containsKey(tenantId));
        log.info("{}", "====================================================");
        if (TenantContextHolder.dataSourceMap.containsKey(tenantId)) {
            return TenantContextHolder.dataSourceMap.get(tenantId);
        }
        // 初始化 默认的数据源
        TenantDbConfigDTO config = new TenantDbConfigDTO();
        config.setTenantId(DbConstants.DEFAULT_DATABASE);
        BeanUtils.copyProperties(dataSourceProperties, config);
        return DataSourceUtils.wrapperDataSource(config);
    }

    /**
     * 　* @description: 添加所有数据源，可以项目启动之后添加，也可以每次用户登录的时候拦截添加
     *
     */
    public void addDataSource(TenantDbConfigDTO config) {
        DataSource dataSource = DataSourceUtils.wrapperDataSource(config);
        log.info(TenantContextHolder.dataSourceMap.getClass().getCanonicalName());
        TenantContextHolder.dataSourceMap.put(config.getTenantId(), dataSource);
    }
}
